在 SpringBoot 官方 Guides Building an Application with Spring Boot 中看到一段如下代码:
1 | package hello; |
其中实现了一个 CommandLineRunner 匿名内部类,那么 CommandLineRunner 接口有哪些作用呢?工作机制又是什么?
SpringBoot Reference 1.5.9.RELEASE 23.8 Using the ApplicationRunner or CommmandLineRunner 中有这么一段话:1
If you need to run some specific code once the SpringApplication has started, you can implement the ApplicationRunner or CommandLineRunner interfaces. Both interfaces work in the same way and offer a single run method which will be called just before SpringApplication.run(…) completes.
创建一个普通的 SpringBoot Application,并编写一个CommandLineRunner 实现类:1
2
3
4
5
6
7
8
9
10
11
12
13
14package com.example.springboot.commandlinerunner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class HelloCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... strings) throws Exception {
System.out.println("Hello CommandLineRunner");
}
}
运行该 SpringBoot Application,控制台将出现如下输出:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 . ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.5.9.RELEASE)
2017-11-29 19:53:28.157 INFO 10544 --- [ main] ingBootCommandLineRunnerHelloApplication : Starting SpringBootCommandLineRunnerHelloApplication on DESKTOP-49M29KH with PID 10544 (D:\lxmuse-spring-boot\spring-boot-command-line-runner\spring-boot-command-line-runner-hello\target\classes started by Richard in D:\lxmuse-spring-boot\spring-boot-command-line-runner\spring-boot-command-line-runner-hello)
2017-11-29 19:53:28.159 INFO 10544 --- [ main] ingBootCommandLineRunnerHelloApplication : No active profile set, falling back to default profiles: default
2017-11-29 19:53:28.220 INFO 10544 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@6dde5c8c: startup date [Wed Nov 29 19:53:28 CST 2017]; root of context hierarchy
2017-11-29 19:53:28.737 INFO 10544 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
Hello CommandLineRunner
2017-11-29 19:53:28.746 INFO 10544 --- [ main] ingBootCommandLineRunnerHelloApplication : Started SpringBootCommandLineRunnerHelloApplication in 0.833 seconds (JVM running for 1.802)
2017-11-29 19:53:28.747 INFO 10544 --- [ Thread-4] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@6dde5c8c: startup date [Wed Nov 29 19:53:28 CST 2017]; root of context hierarchy
2017-11-29 19:53:28.749 INFO 10544 --- [ Thread-4] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans on shutdown
可以发现,在完全启动前已经执行了 HelloCommandLineRunner 中的 run 方法。
Reference 中提到 ApplicationRunner 和 CommmandLineRunner 具有相同的作用。
同理编写一个 ApplicationRunner 实现类:1
2
3
4
5
6
7
8
9
10
11
12
13
14package com.example.springboot.commandlinerunner;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
@Component
public class HelloApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments applicationArguments) throws Exception {
System.out.println("Hello ApplicationRunner");
}
}
重新运行 SpringBoot Application,控制台将出现如下输出:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 . ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.5.9.RELEASE)
2017-11-29 20:02:17.920 INFO 6548 --- [ main] ingBootCommandLineRunnerHelloApplication : Starting SpringBootCommandLineRunnerHelloApplication on DESKTOP-49M29KH with PID 6548 (D:\lxmuse-spring-boot\spring-boot-command-line-runner\spring-boot-command-line-runner-hello\target\classes started by Richard in D:\lxmuse-spring-boot\spring-boot-command-line-runner\spring-boot-command-line-runner-hello)
2017-11-29 20:02:17.922 INFO 6548 --- [ main] ingBootCommandLineRunnerHelloApplication : No active profile set, falling back to default profiles: default
2017-11-29 20:02:17.969 INFO 6548 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@5123a213: startup date [Wed Nov 29 20:02:17 CST 2017]; root of context hierarchy
2017-11-29 20:02:18.534 INFO 6548 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
Hello ApplicationRunner
Hello CommandLineRunner
2017-11-29 20:02:18.546 INFO 6548 --- [ main] ingBootCommandLineRunnerHelloApplication : Started SpringBootCommandLineRunnerHelloApplication in 0.829 seconds (JVM running for 1.294)
2017-11-29 20:02:18.547 INFO 6548 --- [ Thread-4] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@5123a213: startup date [Wed Nov 29 20:02:17 CST 2017]; root of context hierarchy
2017-11-29 20:02:18.548 INFO 6548 --- [ Thread-4] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans on shutdown
可以发现,在完全启动前已经执行了 HelloApplicationRunner 和 HelloCommandLineRunner 中的 run 方法。
并且 HelloApplicationRunner 中的 run 方法优先执行。
那么 @Order 对其有没有影响呢?
在 HelloApplicationRunner 上添加 @Order 注解,并且指定值为 2;
在 HelloCommandLineRunner 上添加 @Order 注解,并且指定值为 1;
重新运行 SpringBoot Application,控制台将出现如下输出:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 . ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.5.9.RELEASE)
2017-11-29 20:09:21.078 INFO 772 --- [ main] ingBootCommandLineRunnerHelloApplication : Starting SpringBootCommandLineRunnerHelloApplication on DESKTOP-49M29KH with PID 772 (D:\lxmuse-spring-boot\spring-boot-command-line-runner\spring-boot-command-line-runner-hello\target\classes started by Richard in D:\lxmuse-spring-boot\spring-boot-command-line-runner\spring-boot-command-line-runner-hello)
2017-11-29 20:09:21.080 INFO 772 --- [ main] ingBootCommandLineRunnerHelloApplication : No active profile set, falling back to default profiles: default
2017-11-29 20:09:21.139 INFO 772 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@5123a213: startup date [Wed Nov 29 20:09:21 CST 2017]; root of context hierarchy
2017-11-29 20:09:21.604 INFO 772 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
Hello CommandLineRunner
Hello ApplicationRunner
2017-11-29 20:09:21.622 INFO 772 --- [ main] ingBootCommandLineRunnerHelloApplication : Started SpringBootCommandLineRunnerHelloApplication in 0.755 seconds (JVM running for 1.256)
2017-11-29 20:09:21.623 INFO 772 --- [ Thread-4] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@5123a213: startup date [Wed Nov 29 20:09:21 CST 2017]; root of context hierarchy
2017-11-29 20:09:21.625 INFO 772 --- [ Thread-4] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans on shutdown
HelloCommandLineRunner 将根据指定的顺序优先执行。
那么相同类型的实现类执行顺序又是如何呢?
其真正的执行原理又是什么呢?
留待再探时再解密吧!(需要深入源码)
具体代码已上传GitHub-lxmuse